package com.zhiwei.msf.gateway.filter;


import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.cloud.netflix.zuul.util.ZuulRuntimeException;

import javax.servlet.ServletException;
import java.io.IOException;

/**
 * 异常处理器: 默认SendErrorFilter开启： com.netflix.zuul.ZuulFilter#isFilterDisabled() 禁用
 * 默认错误器： BasicErrorController#error
 * 注意： 404 不走过滤器
 */
//@Component
@Slf4j
public class ZuulErrorFilter extends ZuulFilter {

    /**
     * 过滤器具体逻辑: 错误页重定向
     */
    @Override
    public Object run() {
        RequestContext context = RequestContext.getCurrentContext();
        try {
            ZuulException zuulException = findZuulException(context.getThrowable());
            log.error("error==> ", zuulException);
            context.getRequest().getRequestDispatcher("/error").forward(context.getRequest(), context.getResponse());
        } catch (ServletException | IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 判断是否启用过滤器
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    /**
     * 过滤器执行顺序
     */
    @Override
    public int filterOrder() {
        return FilterConstants.SEND_ERROR_FILTER_ORDER - 1;
    }

    /**
     * 过滤器类型：
     * pre 表示在请求被路由之前执行
     * post: 表示请求之后执行
     * error： 表示错误处理器
     * routing： 服务名映射处理器：服务名映射为具体服务
     */
    @Override
    public String filterType() {
        return FilterConstants.POST_TYPE;
    }

    private ZuulException findZuulException(Throwable throwable) {
        if (throwable.getCause() instanceof ZuulRuntimeException) {
            return (ZuulException) throwable.getCause().getCause();
        } else if (throwable.getCause() instanceof ZuulException) {
            return (ZuulException) throwable.getCause();
        } else {
            return throwable instanceof ZuulException ? (ZuulException) throwable : new ZuulException(throwable, 500, null);
        }
    }
}